package com.roger.uia.helper;

import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Environment;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.UiCollection;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.util.Log;
import org.junit.Assert;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class UiBase {
    private static final String TAG = "Test" + UiBase.class.getSimpleName();
    public static UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    public static String filePath = Environment.getExternalStorageDirectory() + "/";
    public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMdd_HHmmss", Locale.CHINA);
    public static String [] objSelect = {"txt","txtC","txtM","reid","desc","descC","descM","class"};
    public static String [] direction = {"up","down","left","right"};
    public static int waitTime = 1000;

    @SuppressWarnings("ConstantConditions")
    public static UiObject getObj(String objType, String objStr){
        UiObject obj;
        if(objType.equals(objSelect[0])) obj=mDevice.findObject(new UiSelector().text(objStr));
        else if(objType.equals(objSelect[1])) obj=mDevice.findObject(new UiSelector().textContains(objStr));
        else if(objType.equals(objSelect[2])) obj=mDevice.findObject(new UiSelector().textMatches(objStr));
        else if(objType.equals(objSelect[3])) obj=mDevice.findObject(new UiSelector().resourceId(objStr));
        else if(objType.equals(objSelect[4])) obj=mDevice.findObject(new UiSelector().description(objStr));
        else if(objType.equals(objSelect[5])) obj=mDevice.findObject(new UiSelector().descriptionContains(objStr));
        else if(objType.equals(objSelect[6])) obj=mDevice.findObject(new UiSelector().descriptionMatches(objStr));
        else if(objType.equals(objSelect[7])) obj=mDevice.findObject(new UiSelector().className(objStr));
        else obj = mDevice.findObject(new UiSelector());
        return obj;
    }

    public static boolean existObj(String objType,String objStr){
        Log.d(TAG,"if the obj " + objStr + " exist: " + getObj(objType ,objStr).exists());
        return getObj(objType ,objStr).exists();
    }

    public static boolean objEnabled(String objType, String objStr) throws UiObjectNotFoundException {
        Log.d(TAG,"if the obj " + objStr + " enabled: " + getObj(objType ,objStr).isEnabled());
        return getObj(objType ,objStr).isEnabled();
    }

    public static boolean objChecked(String objType, String objStr) throws UiObjectNotFoundException {
        Log.d(TAG,"if the obj " + objStr + " checked: " + getObj(objType ,objStr).isChecked());
        return getObj(objType ,objStr).isChecked();
    }

    public static boolean objSelected(String objType, String objStr) throws UiObjectNotFoundException {
        Log.d(TAG,"if the obj " + objStr + " Selected: " + getObj(objType ,objStr).isSelected());
        return getObj(objType ,objStr).isSelected();
    }

    public static void waitObj(String objType,String objStr,int sec){
        Log.d(TAG,"wait the obj " + objStr + " for " + sec +"s");
        for (int i = 0; i <= sec; i++) {
            if (existObj(objType,objStr)) break;
            SystemClock.sleep(waitTime);
        }
    }

    public static void waitObjCheck(String objType,String objStr,int sec){
        Log.d(TAG,"wait for the obj " + objStr + " for " + sec +"s");
        for (int i = 0; i <= sec; i++) {
            if (existObj(objType,objStr)) break;
            SystemClock.sleep(waitTime);
            if (i == sec) checkPoint("ERR: wait for " + objStr + " more than " + sec + "s timeout!", false);
        }
    }

    public static void waitObjGone(String objType,String objStr,int sec){
        Log.d(TAG,"wait the obj " + objStr + " disappear for " + sec +"s");
        for (int i = 0; i <= sec; i++) {
            if (!existObj(objType,objStr)) break;
            SystemClock.sleep(waitTime);
        }
    }

    public static void clickObj(String objType,String objStr) throws UiObjectNotFoundException {
        getObj(objType ,objStr).clickAndWaitForNewWindow();
        Log.d(TAG,"click the obj " + objStr + " success");
    }

    public static void clickIfObjExist(String objType,String objStr) throws UiObjectNotFoundException {
        if(existObj(objType,objStr)) clickObj(objType,objStr);
    }

    public static void longClickObj(String objType,String objStr) throws UiObjectNotFoundException {
        int x = getObjX(objType,objStr);
        int y = getObjY(objType,objStr);
        mDevice.swipe(x, y, x, y, 100);
        Log.d(TAG,"long click the obj " + objStr + " success");
    }

    public static void clickTwoObjAtTheSameTime(int x1, int y1, int x2, int y2, int steps){
        Point P1= new Point();
        Point P2= new Point();
        P1.x=x1;P1.y=y1;
        P2.x=x2;P2.y=y2;
        getObj("","").performTwoPointerGesture(P1,P2,P1,P2,steps);
    }

    public static void waitClickObj(String objType,String objStr,int sec) throws UiObjectNotFoundException {
        waitObj( objType,objStr, sec);
        clickObj(objType,objStr);
    }

    public static void waitClickIfObjExist(String objType,String objStr,int sec) throws UiObjectNotFoundException {
        waitObj(objType,objStr,sec);
        clickIfObjExist(objType,objStr);
    }

    public static void scrollReidClickObj(String reidName,String objType,String objStr) throws UiObjectNotFoundException {
        UiScrollable list = new UiScrollable(new UiSelector().resourceId(reidName));
        if(!existObj(objType,objStr)) {
            Log.d(TAG,"scroll list to the obj " + objStr);
            list.scrollIntoView(getObj(objType,objStr));
        }
        clickObj(objType,objStr);
    }

    public static void swipeObj(String objType,String objStr,String direct,int steps) throws UiObjectNotFoundException {
        if (direct.equals(direction[0])) getObj(objType,objStr).swipeUp(steps);
        if (direct.equals(direction[1])) getObj(objType,objStr).swipeDown(steps);
        if (direct.equals(direction[2])) getObj(objType,objStr).swipeLeft(steps);
        if (direct.equals(direction[3])) getObj(objType,objStr).swipeRight(steps);
        Log.d(TAG,"swipe obj " + objStr + " " + direct + " success");
    }

    public static void dragObj(String objType,String objStr,int destX,int destY,int steps) throws UiObjectNotFoundException {
        getObj(objType,objStr).dragTo(destX,destY,steps);
        Log.d(TAG,"drag obj " + objStr + " to " + destX+","+destY + " success");
    }

    public static void inputTxtToObj(String objType,String objStr,String txtStr) throws UiObjectNotFoundException {
        getObj(objType ,objStr).clearTextField();
        getObj(objType ,objStr).setText(txtStr);
        Log.d(TAG,"input " + txtStr + " to " + objStr + " success");
    }

    public static String getTxtFromObj(String objType,String objStr) throws UiObjectNotFoundException {
        return getObj(objType ,objStr).getText();
    }

    public static int getObjX(String objType,String objStr) throws UiObjectNotFoundException {
        return getObj(objType ,objStr).getBounds().centerX();
    }

    public static int getObjY(String objType,String objStr) throws UiObjectNotFoundException {
        return getObj(objType ,objStr).getBounds().centerY();
    }

    private static boolean isObjSameLine(UiObject obj1, UiObject obj2) throws UiObjectNotFoundException {
        Rect first = obj1.getBounds();
        Rect second = obj2.getBounds();
        return first.top < second.bottom && first.bottom > second.top;
    }

    public static UiObject getObjSameLine(UiCollection uic, UiObject obj1, UiObject obj2) throws UiObjectNotFoundException {
        UiObject obj = null;
        UiSelector uis = obj2.getSelector();
        for(int i=0; i< uic.getChildCount(uis); i++){
            UiObject uiObject = uic.getChildByInstance(uis, i);
            if(isObjSameLine(obj1, uiObject)){
                obj = uiObject;
                break;
            }
        }
        return obj;
    }

    public static List<String> getListText(String listReid,String objReid) throws UiObjectNotFoundException {
        List<String> lists =new ArrayList<>();
        UiScrollable uis = new UiScrollable(new UiSelector().resourceId(listReid));
        UiCollection uic = new UiCollection(new UiSelector().resourceId(listReid));
        UiObject obj=UiBase.getObj(UiBase.objSelect[3],objReid);
        uis.scrollToBeginning(50);
        for (int x = 0; x < 5; x++) {
            for(int i=0; i< uic.getChildCount(obj.getSelector()); i++){
                String s=uic.getChildByInstance(obj.getSelector(), i).getText();
                if(!lists.contains(s))  lists.add(s);
            }
            uis.scrollForward();
        }
        return lists;
    }

    public static void checkPoint(String msg, boolean statue) {
        Date curDate = new Date(System.currentTimeMillis());
        String time = dateFormat.format(curDate);
        Assert.assertTrue(time + ":" + msg, statue);
    }

    public static void openApp(String packageName) {
        Log.d(TAG,"start app " + packageName);
        Context context = InstrumentationRegistry.getContext();
        Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
        context.startActivity(intent);
    }

    public static void startApp(String activityName) throws IOException {
        Log.d(TAG,"start app " + activityName);
        mDevice.executeShellCommand("am start -n "+ activityName);
    }

    public static void startApp2(String pac) throws IOException {
        Log.d(TAG,"start app " + pac);
        mDevice.executeShellCommand("monkey -p "+ pac + " -c android.intent.category.LAUNCHER 1");
    }

    public static void forceStopApp(String packageName) throws IOException {
        Log.d(TAG,"force stop app " + packageName);
        mDevice.executeShellCommand("am force-stop "+packageName);
    }

    public static void clearApp(String packageName) throws IOException {
        Log.d(TAG,"clear app " + packageName);
        mDevice.executeShellCommand("pm clear "+packageName);
    }

    public static void enableApp(String packageName) throws IOException {
        Log.d(TAG,"enable app " + packageName);
        mDevice.executeShellCommand("pm enable "+packageName);
    }

    public static void disableApp(String packageName) throws IOException {
        Log.d(TAG,"disable app " + packageName);
        mDevice.executeShellCommand("pm disable-user "+packageName);
    }

    public static void startAct(String str){
        Intent intent=new Intent(str);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        InstrumentationRegistry.getContext().startActivity(intent);
    }

}